class x_GameInfo extends UDKGame
	config(xLED);

//=============================================================================
// Variables
//=============================================================================
//var globalconfig string                 mLanguage;
var private xDB_Manager			        mDatabaseManager;
var private xDB_Provider                mDatabaseProvider;    //database stored objects provider
var private x_File_Manager			    mFileManager;
var private x_SaveLoadMgr				mSaveLoadMgr;

var private x_PlayerController			localPlayerController; // Private reference to player controller. Can be "GET" from function

//=============================================================================
// Functions: Overrided non-used
//=============================================================================
function RestartPlayer(Controller NewPlayer); // We do not need pawn possessed to our controller.
//function StartOnlineGame(); // And no online game we need
//function OnLoginChange(byte LocalUserNum);
//function bool ProcessServerLogin();
//function RegisterServer();
//event PreBeginPlay();
//event InitGame( string Options, out string ErrorMessage );
//event PreLogin(string Options, string Address, out string ErrorMessage);

//=============================================================================
// Functions: Get references
//=============================================================================
/**
 * Get the created database manager object.
 * 
 * @return Allocated xDB_Manager object
 */
final function xDB_Manager getDBMgr()
{
	return mDatabaseManager;
}

/**
 * Get database provider of stored objects
 * 
 * @return Allocated xDB_Manager object
 */
final function xDB_Provider getDbProvider()
{
	return mDatabaseProvider;
}


/**
 * Get the created file manager object.
 * 
 * @return Allocated X_COM_FileMgr object
 */
final function x_File_Manager getFileMgr()
{
	return mFilemanager;
}

/**
 * Get the created savegame manager object.
 * 
 * @return Allocated X_COM_SaveLoadMgr object
 */
final function x_SaveLoadMgr getSaveLoadMgr()
{
	return mSaveLoadMgr;
}

function x_PlayerController GetPlayerController()
{
	return localPlayerController;
}

//=============================================================================
// Events: 
//=============================================================================
/** First called event at game startup. */ 
event InitGame( string Options, out string ErrorMessage )
{
//	local string lLang; //loaded language

	Super.InitGame(Options, ErrorMessage);

	mDatabaseManager = Spawn(class'xDB_Manager', self);
	mDatabaseProvider = Spawn(class'xDB_Provider', mDatabaseManager);       `log("x_GameInfo::InitGame:xDB_Provider = "$mDatabaseProvider);
	mFilemanager = Spawn(class'x_File_Manager', mDatabaseManager);
	mSaveLoadMgr = Spawn(class'x_SaveLoadMgr', mDatabaseManager);

	performServerTravelDone(Options); // call to load DB files into memory

	//TODO move this under if with the config flag "Run database tests" 
	RunDatabaseTests();
	CreateSoldierInventories();
}

event PostLogin( PlayerController NewPlayer )
{
    super.PostLogin(NewPlayer);
	localPlayerController = x_PlayerController(NewPlayer); // Save reference of player controller which can be get in GET-function
	StartGame(); // main start game
}

//=============================================================================
// Server Travel: 
//=============================================================================
function performServerTravel(string aURL)
{
	// We do not need to save gameplay DB to disk if we are exiting to main menu
	if (((Class == class'x_GameInfo') && (aURL == class'x_Settings'.default.GEOmap)) || (Class != class'x_GameInfo'))// if new game or load game and transition db if we are going from GEO->Tactics->GEO
	{
		mFilemanager.saveTransition(); // Save temporary DB
	}
	WorldInfo.ServerTravel(aURL);
}

function performServerTravelDone(string aOptions)
{
	if(Class == class'x_GameInfo') // We do not need to load gameplay DB from disk if we are exiting to main menu
	{
		mDatabaseManager.loadGameContentDatabase();
		mDatabaseManager.loadDefaultGameplayDatabase();
		mDatabaseManager.loadLocalizationDatabase();
		mDatabaseManager.loadSavedGamesDatabase();
	}
	else
	{
		mDatabaseManager.loadGameContentDatabase();
		mDatabaseManager.loadLocalizationDatabase();
		mDatabaseManager.loadSavedGamesDatabase();
		mFileManager.loadTransition();
		mFileManager.DeleteTransition(); // delete temp transition db file
	}
}

//=============================================================================
// Functions:
//=============================================================================
static function bool UseLowGore(WorldInfo WI)
{
	return (Default.GoreLevel > 0) && (WI.NetMode != NM_DedicatedServer);
}

function StartGame()
{
	StartMatch();
}

//=============================================================================
// Database tests and examples
//=============================================================================

/**
 * Ok consider it to be the manual to all the XCOM SQLite database system FOR USERS.
 * By 'FOR USERS' I mean programmers, who work on the other parts of the game and
 * should not bother themselves by LEFT JOINS and querries. So instead of querries
 * users can use "Providers" and regular classes. 
 * 
 * Ok, here we came to the two main concepts of the xDB, 
 * 1) Providers and
 * 2) Info classes
 * 
 * - Provider classes work with DB, all querries are executed inside the Provider classes. 
 * Provider classes read DB and return data to user in form of "Info" classes. 
 * 
 * - "Info" classes represents data stored in the database. They have fields that 
 * match realted fields in the database, but also "Info" classes have functions 
 * represents logical connection between data in the database. Like you have
 * soldier.GetInventory() instead of getting inventory "Info" class through InventoryId
 * 
 * Sometimes example worth more than words; The next function is full of examples, 
 * but let me put one example in this comments since this functionality is not 
 * implemented yet =p
 * 
 * @example
 * //lets say we have a provider
 * local xDB_Provider lProvider;
 * 
 * //read the xDB_Info_Soldier record from the db by id. 
 * lDbSoldier = lProvider.GetSoldierById(1);
 * 
 * // Soldier record in the database have field InventoryId, by which you could
 * //reference to Inventory table  and get a data on inventory. 
 * //But "Info" classes try to make it for you. 
 * lInventory = lDbSoldier.GetInventory();   // This function will return loaded 
 *                                           // xDB_Info_Inventory class, 
 * 
 * @example end
 * 
 * What happend? Actually, to get inventory lDbSoldier class will refer to a provider 
 * that loaded 'him', and use Provider.GetInventoyById(...) function to load coresponding 
 * data on soldier inventory. But user dont have to know all this. 
 * Just use lDbSoldier.GetInventory() which is logical.
 * And "Info" classes will do everything for you. 
 */
function RunDatabaseTests()
{
	local string lLang;  //test phrase from localization
	local xDB_Provider lProvider;                //database provider
	local xDB_Info_Inventory lInventory;         //test inventary
	local array<xDB_Info_InventoryItem> lInventoryItems;   //items from test inventory
	local xDB_Info_InventoryItem lInventoryItem;
	local xDB_Info_Item lItemInfo;
	local string lStr; //just temporary string for experiments
	local int i;

	//Get game info and provider
	lProvider = getDbProvider();

	// * * *   T E S T   L O C A L I Z A T I O N   * * *
	//Test localization
	lLang = lProvider.GetPhrase("Language");
	`log("Current language is "$lLang);

	// * * *   T E S T   I N V E N T O R Y   * * *	
	lInventory = lProvider.GetInventoryById(1);     //we assume that inventory with Id=1 is a test inventory

	//If there were some errors on load objects None will be returned
	if(lInventory == None)
	{
		`warn("Was unable to lProvider.GetInventoryById(1); None returned ");
		return; //we have nothing to do here more...
	}

	lInventoryItems = lInventory.GetItems();        //Get inventory items
	`log("Inventory has items: "$lInventoryItems.Length);

	//we have nothing to do if we have no items in inventory
	if(lInventoryItems.Length == 0) return; 
	
	//lets play with first item in the inventory;
	lInventoryItem = lInventoryItems[0];

	//lInventoryItem.GetItem() returns xDB_Info_Item - which represents information about item type, and 
	lItemInfo = lInventoryItem.GetItem();
	lStr = lInventoryItem.GetItem().GetName();
	`log("First item in inventory is: "$lStr);
	`log("Item loaded as : "$lInventoryItem.GetLoad()$" of "$lItemInfo.GetMaxLoad());
	`log("Item quantity is : "$lInventoryItem.GetQuantity());
	
	//lets show every item in the inventory
	`log("What we have in inventory?");
	for(i=0; i<lInventoryItems.Length; i++)
	{
		`log("   "$lInventoryItems[i].GetQuantity()$" of "$lInventoryItems[i].GetItem().GetName());
	}

	

	// now lets change item quantity, item load and position in the inventory grid.
	lInventoryItem.SetQuantity(2);
	lInventoryItem.SetLoad(12);
	lInventoryItem.MoveInInventory(2,2);
	
	//but you can change only one coordinate
	lInventoryItem.SetGridX(1); // so now item is (1,2) in the grid

	// (!!!)  right now we have changed lInventoryItem but this changes are NOT saved to DB
		
	//Check if the object was changet from its original state. Just you to know how to do this... 
	if(lInventoryItem.IsChanged()) `log("Item has changes"); else `log("Item has NO changes");

	//save changes to the database
	lInventoryItem.SubmitChanges();

	//After we saved item to database .IsChanged() will be FALSE, indicating thad data is persisting
	if(lInventoryItem.IsChanged()) `log("Item has changes"); else `log("Item has NO changes");

	// * * *   R U N   P E R F O R M A N C E   T E S T S * * * 
	RunDatabasePerformanceTests();
}


//=============================================================================
// Database tests and examples
//=============================================================================

/**
 * 
 */
function RunDatabasePerformanceTests()
{
	local float lClockTime;
	local xDB_Info_Item lItemInfo;
	local xDB_Info_Inventory lInventory;         //test inventary
	local array<xDB_Info_InventoryItem> lInventoryItems;   //items from test inventory
	local xDB_Info_InventoryItem lInventoryItem;
//	local string lStr; //just temporary string for experiments
	local int i;
	
	//* * *   G E T   I T E M   P E R F O R M A N C E   * * * 

	Clock( lClockTime );
	for(i=0; i<300; i++)
	{
		lItemInfo = mDatabaseProvider.GetItemById(1); //suppose it is a test item
	}
	UnClock( lClockTime );
	
	`log("300 get items was done by "$lClockTime);

		
	//* * *   I N V E N T O R Y   I T E M   P E R F O R M A N C E   * * * 
	Clock( lClockTime );
	for(i=0; i<100; i++)
	{
		lInventory = mDatabaseProvider.GetInventoryById(1);     //we assume that inventory with Id=1 is a test inventory
		lInventoryItems = lInventory.GetItems();        //Get inventory items
		if(lInventoryItems.Length == 0) return; //we have nothing to do if we have no items in inventory
	
		//lets play with first item in the inventory;
		lInventoryItem = lInventoryItems[0];

		// now lets change item quantity, item load and position in the inventory grid.
		lInventoryItem.SetQuantity(2);
		lInventoryItem.SetLoad(12);
		lInventoryItem.MoveInInventory(2,2);
		//Check if the object was changet from its original state. Just you to know how to do this... 
		if(lInventoryItem.IsChanged()) 
		{
			//save changes to the database
			lInventoryItem.SubmitChanges();
		}
	}

	UnClock( lClockTime );
	
	`log("100 inventory items update was done by "$lClockTime);
}

function CreateSoldierInventories()
{
	local string lLang;  //test phrase from localization
	local xDB_Provider lProvider;                //database provider
	local xDB_Info_Inventory lInventory;         //test inventary
	local array<xDB_Info_InventoryItem> lInventoryItems;   //items from test inventory
	local xDB_Info_InventoryItem lInventoryItem;
	local xDB_Info_Item lItemInfo;
	local string lStr; //just temporary string for experiments
	local int i;

	//Get game info and provider
	lProvider = getDbProvider();

	// * * *   T E S T   L O C A L I Z A T I O N   * * *
	//Test localization
	lLang = lProvider.GetPhrase("Language");
	`log("Current language is "$lLang);

	// * * *   C R E A T E   I N V E N T O R Y S   * * *
	for(i=0; i<10; i++)
	{
		lInventory = lProvider.CreateInventory();     //we assume that inventory with Id=1 is a test inventory
		lInventory.AddItemByName("Weapons_Riffle.Human.Riffle", 1, 1, 0, 0);
		`log("Add Weapons_Riffle.Human.Riffle");
	}
	//If there were some errors on load objects None will be returned
	/*if(lInventory == None)
	{
		`warn("Was unable to lProvider.GetInventoryById(1); None returned ");
		return; //we have nothing to do here more...
	}

	lInventoryItems = lInventory.GetItems();        //Get inventory items
	`log("Inventory has items: "$lInventoryItems.Length);

	//we have nothing to do if we have no items in inventory
	if(lInventoryItems.Length == 0) return; 
	
	//lets play with first item in the inventory;
	lInventoryItem = lInventoryItems[0];

	//lInventoryItem.GetItem() returns xDB_Info_Item - which represents information about item type, and 
	lItemInfo = lInventoryItem.GetItem();
	lStr = lInventoryItem.GetItem().GetName();
	`log("First item in inventory is: "$lStr);
	`log("Item loaded as : "$lInventoryItem.GetLoad()$" of "$lItemInfo.GetMaxLoad());
	`log("Item quantity is : "$lInventoryItem.GetQuantity());
	
	//lets show every item in the inventory
	`log("What we have in inventory?");
	for(i=0; i<lInventoryItems.Length; i++)
	{
		`log("   "$lInventoryItems[i].GetQuantity()$" of "$lInventoryItems[i].GetItem().GetName());
	}

	

	// now lets change item quantity, item load and position in the inventory grid.
	lInventoryItem.SetQuantity(2);
	lInventoryItem.SetLoad(12);
	lInventoryItem.MoveInInventory(2,2);
	
	//but you can change only one coordinate
	lInventoryItem.SetGridX(1); // so now item is (1,2) in the grid

	// (!!!)  right now we have changed lInventoryItem but this changes are NOT saved to DB
		
	//Check if the object was changet from its original state. Just you to know how to do this... 
	if(lInventoryItem.IsChanged()) `log("Item has changes"); else `log("Item has NO changes");

	//save changes to the database
	lInventoryItem.SubmitChanges();

	//After we saved item to database .IsChanged() will be FALSE, indicating thad data is persisting
	if(lInventoryItem.IsChanged()) `log("Item has changes"); else `log("Item has NO changes");*/
}
//=============================================================================
// Default Properties: 
//=============================================================================
defaultproperties
{
	bDelayedStart = FALSE
	PlayerControllerClass=class'xLED_GAME.x_PlayerController'
	//HUDType=class'xLED_GAME.x_HUD' //turned off to make frontend main menu works propertly
}